import { FastWorkerRaw } from './workers'

class FastWorkerProxy {
  get disposed() {
    throw new Error('Property not implemented.')
  }
  dispose() {
    throw new Error('Function not implemented.')
  }
}

export const createProxyByInvokeMethod = (invokeMethod: (method: string, args: any[]) => Promise<any>) => {
  const methods = Object.create(null)

  const proxy = new Proxy(methods, {
    get: (target, method, receiver) => {
      if (typeof method === 'string' && !method.startsWith('_')) {
        return target[method] ?? (target[method] = (...args: any[]) => invokeMethod(method, args))
      } else {
        return Reflect.get(target, method, receiver)
      }
    }
  })

  return proxy
}

export const createProxy = (workers: FastWorkerRaw<any>) => {
  const proxy = new Proxy(new FastWorkerProxy(), {
    get: (target, method, receiver) => {
      switch (method) {
        case 'dispose':
          return workers.dispose
        case 'disposed':
          return workers.disposed
      }

      if (typeof method === 'string' && !method.startsWith('_')) {
        return workers.getMethod(method)
      } else {
        return Reflect.get(target, method, receiver)
      }
    },
    has: (target, method) => {
      return method in workers.methods || Reflect.has(target, method)
    },
    ownKeys: target => {
      const _ownKeys = Array.from(Reflect.ownKeys(target))
      _ownKeys.push(...Object.keys(workers.methods))
      return _ownKeys
    }
  })

  return proxy
}
